datasg  segment
maxlen  db  11
NUM     db  ?
str1    db  11  dup(0)  ; 包括回车需要接受11个字符
datasg  ends

stacksg segment stack
    dw  40H dup(0)
stacksg ends

codesg  segment
    assume  ds:datasg, ss:stacksg, cs:codesg
start:  mov ax, datasg  ; 初始化DS
        mov ds, ax
        lea dx, maxlen  ; 输入字符串并回显
        mov ax, 0a00H
        int 21H
        mov al, NUM  ; 通过栈传递参数
        mov ah, 0H
        push ax
        mov ax, offset str1
        push ax
        call CONV       ; 调用转换函数
        mov al, NUM     ; 通过栈传递参数
        mov ah, 0H
        push ax
        mov ax, offset str1
        push ax
        call CHK        ; 调用判断函数
        lea dx, str1    ; 打印字符串
        mov ax, 0900H
        int 21H

        mov ax, 4c00H   ; 返回DOS
        int 21H

CONV    PROC    NEAR
        mov bp, sp      ; 获取参数
        push ax ; 保护现场
        push cx
        push di

        mov di, [bp+2]
        mov cx, [bp+4]
        jcxz quit
lop:    mov al,[di]
        cmp al, '9'
        jbe L0
        jmp Lz
L0:     cmp al, '0'
        jae st0
        jmp nt
st0:    mov byte ptr [di], 0H
Lz:     cmp al, 'z'
        jbe la
        jmp nt
La:     cmp al, 'a'
        jae Cv
        jmp nt
cv:     and byte ptr [di], 11011111B
nt:     inc di
        loop lop

quit:   pop di  ; 恢复现场
        pop cx
        pop ax
        ret 4   ; 清除堆栈中的入口参数
CONV    ENDP

CHK     PROC
        mov bp, sp
        push cx
        push di

        mov di, [bp+2]
        mov cx, [bp+4]
        jcxz NET
lop2:   mov al, [di]
        cmp al, 0H
        lahf
        inc di
        sahf
        loopz lop2
        jnz ext
        mov di, [bp+2]
        mov byte ptr [di], '?'
ext:    mov cx, [bp+4]
        add di, cx
        mov byte ptr [di], '$'
quit2:  pop di
        pop cx
        ret 4
net:    mov di, [bp+2]
        mov byte ptr [di], '?'
        mov byte ptr [di+1], '$'
        pop di
        pop cx
        ret 4

CHK     ENDP

codesg  ends
    end start
